from random import sample
from django.utils import timezone
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from .models import ReciteSession, ReciteRecord
from .serializers import ReciteSessionSerializer, ReciteRecordSerializer
# 假设这几个模型在 words 应用中
from words.models import Noun, Verb, Adjective, Other
from datetime import timedelta
from django.db.models import Count, functions





class ReciteStatsView(APIView):
    """
    返回用户在 recite 里的各种统计数据。
    """
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        user = request.user

        # ========== 1. 统计“已掌握词汇数”（去重计数）==========
        # 比如您定义 “is_known=True” 表示掌握，且根据 (word_type, word_id) 去重
        # Django 默认去重可以用 distinct()，但是要注意 PostgreSQL / MySQL 不同写法
        vocabulary_count = (
            ReciteRecord.objects
            .filter(user=user, is_known=True)
            .values('word_type', 'word_id')
            .distinct()
            .count()
        )

        # ========== 2. 统计“昨日背诵单词数” ==========
        # 定义“昨日”区间 [昨天 00:00, 昨天 23:59:59]
        today = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0)
        yesterday_start = today - timedelta(days=1)
        yesterday_end = today - timedelta(microseconds=1)

        # 计算昨天新增学习/复习过的单词数
        # 这里示例按 ReciteRecord.last_study_time 判断
        yesterday_word_count = (
            ReciteRecord.objects
            .filter(
                user=user,
                last_study_time__range=(yesterday_start, yesterday_end)
            )
            .values('word_type', 'word_id')
            .distinct()
            .count()
        )

        # ========== 3. 统计“最近 30 天背诵数据” ==========
        # 这里示例：按日期分组，统计每天学习/复习的单词量
        # 先取 30 天内的记录
        past_30_days_start = today - timedelta(days=30)
        qs_30 = (
            ReciteRecord.objects
            .filter(user=user, last_study_time__gte=past_30_days_start)
            .annotate(date_only=functions.TruncDate('last_study_time'))
            .values('date_only')
            .annotate(words_count=Count('id', distinct=True))
            .order_by('date_only')
        )
        # 转化成字典 {date: count}
        daily_map = {item['date_only']: item['words_count'] for item in qs_30}
        # 为了返回给前端方便，可以再组装成数组
        # 例: [ { date: '2024-01-01', count: 5 }, ... ]
        daily_stats = []
        for i in range(30, 0, -1):  # 从 30 天前到昨天
            d = (today - timedelta(days=i)).date()
            daily_stats.append({
                'date': d.isoformat(),
                'count': daily_map.get(d, 0)
            })
        # 也可包含今天:
        daily_stats.append({
            'date': today.date().isoformat(),
            'count': daily_map.get(today.date(), 0)
        })

        return Response({
            'vocabulary_count': vocabulary_count,
            'yesterday_word_count': yesterday_word_count,
            'daily_stats': daily_stats
        })

class LevelsInfoView(APIView):
    """
    GET: 获取所有等级（1~6、7）及强变化动词的剩余词汇数量
    """
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        user = request.user
        levels = range(1, 8)  # 1-6, 7 for TestDaF
        data = []

        # 取出当前用户所有背诵记录
        user_records = ReciteRecord.objects.filter(user=user)
        noun_ids = user_records.filter(word_type='N').values_list('word_id', flat=True)
        verb_ids = user_records.filter(word_type='V').values_list('word_id', flat=True)
        adj_ids = user_records.filter(word_type='A').values_list('word_id', flat=True)
        oth_ids = user_records.filter(word_type='O').values_list('word_id', flat=True)

        for lvl in levels:
            # 1) 统计总数
            noun_count = Noun.objects.filter(level=lvl).count()
            verb_count = Verb.objects.filter(level=lvl).count()
            adj_count = Adjective.objects.filter(level=lvl).count()
            other_count = Other.objects.filter(level=lvl).count()
            total_words = noun_count + verb_count + adj_count + other_count

            # 2) 统计剩余（未背过）的单词数
            leftover_nouns = Noun.objects.filter(level=lvl).exclude(id__in=noun_ids).count()
            leftover_verbs = Verb.objects.filter(level=lvl).exclude(id__in=verb_ids).count()
            leftover_adjs = Adjective.objects.filter(level=lvl).exclude(id__in=adj_ids).count()
            leftover_oths = Other.objects.filter(level=lvl).exclude(id__in=oth_ids).count()
            leftover_total = leftover_nouns + leftover_verbs + leftover_adjs + leftover_oths

            data.append({
                "level": lvl,
                "total_words": total_words,
                "leftover_words": leftover_total,
            })

        # 额外统计“强变化动词”
        stark_verbs_total = Verb.objects.filter(stark=True).count()
        user_stark_ids = user_records.filter(word_type='V',
                                             word_id__in=Verb.objects.filter(stark=True).values_list('id', flat=True)
                                             ).values_list('word_id', flat=True)
        leftover_stark = Verb.objects.filter(stark=True).exclude(id__in=user_stark_ids).count()

        return Response({
            "levels_info": data,
            "stark_verbs": {
                "total_words": stark_verbs_total,
                "leftover_words": leftover_stark,
            }
        })


def get_word_details(word_type, word_id):
    """
    辅助函数：根据 word_type & word_id，查询对应表并返回需要的字段。
    返回一个 dict:
    {
        "word": "...",
        "chinese": "...",
        "sentences": [...],
        "chinese_sentences": [...],
        "level": ...
        # 如果是动词，还可返回 p1, p2 等等
    }
    """
    details = {}
    if word_type == 'N':
        noun = Noun.objects.get(id=word_id)
        details = {
            "word": noun.word,
            "chinese": noun.chinese,
            "sentences": noun.sentence.split("#") if noun.sentence else [],
            "chinese_sentences": noun.chinese_sentence.split("#") if noun.chinese_sentence else [],
            "level": noun.level,
            "gender": noun.gender,
            "plurals": noun.plurals,
        }
    elif word_type == 'V':
        verb = Verb.objects.get(id=word_id)
        details = {
            "word": verb.word,
            "chinese": verb.chinese,
            "sentences": verb.sentence.split("#") if verb.sentence else [],
            "chinese_sentences": verb.chinese_sentence.split("#") if verb.chinese_sentence else [],
            "level": verb.level,
            "stark": verb.stark,
            "divisible": verb.divisible,
            "reflexive": verb.reflexive,
            "auxiliary": verb.auxiliary,
            "p1": verb.p1,
            "p2": verb.p2,
            "a1": verb.a1,
            "a2": verb.a2,
            "a3": verb.a3,
            "a4": verb.a4,
            "a5": verb.a5,
            "a6": verb.a6,
            "b1": verb.b1,
            "b2": verb.b2,
            "b3": verb.b3,
            "b4": verb.b4,
            "b5": verb.b5,
            "b6": verb.b6,
            "verb_class": verb.verb_class,
        }
    elif word_type == 'A':
        adj = Adjective.objects.get(id=word_id)
        details = {
            "word": adj.word,
            "chinese": adj.chinese,
            "sentences": adj.sentence.split("#") if adj.sentence else [],
            "chinese_sentences": adj.chinese_sentence.split("#") if adj.chinese_sentence else [],
            "level": adj.level,
        }
    elif word_type == 'O':
        oth = Other.objects.get(id=word_id)
        details = {
            "word": oth.word,
            "chinese": oth.chinese,
            "sentences": oth.sentence.split("#") if oth.sentence else [],
            "chinese_sentences": oth.chinese_sentence.split("#") if oth.chinese_sentence else [],
            "level": oth.level,
        }
    return details


class StartReciteView(APIView):
    """
    POST: 创建一个新的 ReciteSession 并随机抽取指定数量的单词进行背诵。
    Body:
    {
        "level": 1,       # 可选
        "count": 10,      # 必传（要背多少个）
        "is_stark": false # 是否强变化动词模式
    }
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user
        level = request.data.get("level", None)
        count = request.data.get("count", 10)  # 默认一次背10个
        is_stark = request.data.get("is_stark", False)

        # 1. 检查是否有待完成的复习任务
        pending_reviews = ReciteRecord.objects.filter(
            user=user,
            next_review_date__lte=timezone.now().date()
        )
        if pending_reviews.exists():
            return Response({
                "detail": "您有待完成的复习任务，请先完成复习后再开始新的背诵。"
            }, status=status.HTTP_400_BAD_REQUEST)

        if not level and not is_stark:
            return Response({"detail": "level 或 is_stark 必须至少指定一个。"}, status=status.HTTP_400_BAD_REQUEST)

        # 新建一个 ReciteSession
        session_type = ReciteSession.SessionType.RECITATION
        session = ReciteSession.objects.create(user=user, total_words=count, session_type=session_type)

        # 当前用户已背诵的记录
        user_records = ReciteRecord.objects.filter(user=user)
        noun_ids = user_records.filter(word_type='N').values_list('word_id', flat=True)
        verb_ids = user_records.filter(word_type='V').values_list('word_id', flat=True)
        adj_ids = user_records.filter(word_type='A').values_list('word_id', flat=True)
        oth_ids = user_records.filter(word_type='O').values_list('word_id', flat=True)

        chosen_words = []

        if is_stark:
            # 只从强变化动词里随机
            queryset = Verb.objects.filter(stark=True).exclude(id__in=verb_ids)
            all_ids = list(queryset.values_list('id', flat=True))
            chosen = sample(all_ids, min(len(all_ids), count))
            for cid in chosen:
                chosen_words.append({'word_type': 'V', 'word_id': cid})
        else:
            if not level:
                return Response({"detail": "如果不选择强变化动词，请指定等级。"}, status=status.HTTP_400_BAD_REQUEST)
            # 从 level 对应的单词中随机
            noun_all = list(Noun.objects.filter(level=level).exclude(id__in=noun_ids).values_list('id', flat=True))
            verb_all = list(Verb.objects.filter(level=level).exclude(id__in=verb_ids).values_list('id', flat=True))
            adj_all = list(Adjective.objects.filter(level=level).exclude(id__in=adj_ids).values_list('id', flat=True))
            oth_all = list(Other.objects.filter(level=level).exclude(id__in=oth_ids).values_list('id', flat=True))

            combined = [('N', x) for x in noun_all] + \
                       [('V', x) for x in verb_all] + \
                       [('A', x) for x in adj_all] + \
                       [('O', x) for x in oth_all]

            if not combined:
                return Response({"detail": "没有可供背诵的单词。"}, status=status.HTTP_400_BAD_REQUEST)

            chosen = sample(combined, min(len(combined), count))
            for wt, cid in chosen:
                chosen_words.append({'word_type': wt, 'word_id': cid})

        # 建立 ReciteRecord，并收集创建好的对象
        records_created_objs = []
        for cw in chosen_words:
            rcd = ReciteRecord.objects.create(
                user=user,
                session=session,
                word_type=cw['word_type'],
                word_id=cw['word_id'],
                is_known=False,
                study_count=0,  # 初始学习时设置 study_count 为 0
            )
            # 调度下次复习日期
            rcd.schedule_next_review()
            records_created_objs.append(rcd)

        # ============ 组装要返回给前端的 records 详情 ============
        records_data = []
        for rcd in records_created_objs:
            word_data = get_word_details(rcd.word_type, rcd.word_id)
            record_info = {
                "id": rcd.id,
                "word_type": rcd.word_type,
                "word_id": rcd.word_id,
                "is_known": rcd.is_known,
                "study_count": rcd.study_count,
                "next_review_date": rcd.next_review_date,
                **word_data,  # 合并 word_data 字段
            }
            records_data.append(record_info)
        # ========================================================

        # 返回 session 的序列化数据
        serializer = ReciteSessionSerializer(session)

        return Response({
            "session": serializer.data,
            "record_ids": [r.id for r in records_created_objs],  # 保留原有的 id 列表也可以
            "records": records_data,  # 这里直接返回单词详细信息
            "detail": "成功创建背诵任务并分配单词。"
        }, status=status.HTTP_201_CREATED)


class StartReviewView(APIView):
    """
    POST: 创建一个新的 ReviewSession 并获取要复习的单词。
    Body:
    {
        "review_type": "scheduled" | "word_challenge",
        "count": 10  # 可选，若 review_type="word_challenge", 可以指定要复习的单词数量
    }
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user
        review_type = request.data.get("review_type", "scheduled")
        count = request.data.get("count", 10)  # 默认复习10个

        if review_type not in ['scheduled', 'word_challenge']:
            return Response({"detail": "review_type 必须是 'scheduled' 或 'word_challenge'。"}, status=status.HTTP_400_BAD_REQUEST)

        # 检查是否有正在进行的会话
        ongoing_sessions = ReciteSession.objects.filter(user=user, end_time__isnull=True)
        if ongoing_sessions.exists():
            return Response({"detail": "您有正在进行的背诵或复习任务，请先完成或取消它们。"}, status=status.HTTP_400_BAD_REQUEST)

        if review_type == 'scheduled':
            queryset = ReciteRecord.objects.filter(
                user=user,
                next_review_date__lte=timezone.now().date()
            ).order_by('next_review_date')
            total_pending = queryset.count()
            if total_pending == 0:
                return Response({"detail": "没有需要复习的单词。"}, status=status.HTTP_400_BAD_REQUEST)
            chosen_records = queryset[:count]
            if not chosen_records.exists():
                return Response({"detail": "没有足够的需要复习的单词。"}, status=status.HTTP_400_BAD_REQUEST)
        elif review_type == 'word_challenge':
            # 获取所有已学习过的单词，不依赖时间
            queryset = ReciteRecord.objects.filter(
                user=user,
                study_count__gte=1
            ).order_by('?')  # 随机顺序
            if not queryset.exists():
                return Response({"detail": "您还没有足够的单词进行挑战。"}, status=status.HTTP_400_BAD_REQUEST)
            chosen_records = queryset[:count]

        # 创建新的 ReciteSession
        if review_type == 'scheduled':
            session_type = ReciteSession.SessionType.SCHEDULED_REVIEW
        else:
            session_type = ReciteSession.SessionType.WORD_CHALLENGE

        session = ReciteSession.objects.create(user=user, total_words=chosen_records.count(), session_type=session_type)

        records_data = []

        if review_type == 'scheduled':
            # 关联现有的 ReciteRecord 到新的会话
            for rcd in chosen_records:
                rcd.session = session
                rcd.save()
                word_data = get_word_details(rcd.word_type, rcd.word_id)
                record_info = {
                    "id": rcd.id,
                    "word_type": rcd.word_type,
                    "word_id": rcd.word_id,
                    "is_known": rcd.is_known,
                    "study_count": rcd.study_count,
                    "next_review_date": rcd.next_review_date,
                    **word_data,  # 合并 word_data 字段
                }
                records_data.append(record_info)
        elif review_type == 'word_challenge':
            # 不创建新的 ReciteRecord，直接返回单词信息
            for rcd in chosen_records:
                word_data = get_word_details(rcd.word_type, rcd.word_id)
                record_info = {
                    "id": rcd.id,
                    "word_type": rcd.word_type,
                    "word_id": rcd.word_id,
                    "is_known": rcd.is_known,
                    "study_count": rcd.study_count,
                    "next_review_date": rcd.next_review_date,
                    **word_data,  # 合并 word_data 字段
                }
                records_data.append(record_info)

        # 返回 session 数据
        serializer = ReciteSessionSerializer(session)

        return Response({
            "session": serializer.data,
            "record_ids": [r.id for r in chosen_records],
            "records": records_data,
            "session_id": session.id,
            "detail": "成功创建复习任务并分配单词。"
        }, status=status.HTTP_201_CREATED)


class UpdateReciteRecordView(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user
        record_id = request.data.get("record_id", None)
        is_known = request.data.get("is_known", None)
        stage = request.data.get("stage", None)  # 新增 stage 字段

        if not record_id:
            return Response({"detail": "record_id 必填"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            rcd = ReciteRecord.objects.get(id=record_id, user=user)
        except ReciteRecord.DoesNotExist:
            return Response({"detail": "记录不存在或不属于该用户。"}, status=status.HTTP_404_NOT_FOUND)

        # 更新 is_known
        if is_known is not None:
            rcd.is_known = 1

        # 更新 stage
        if stage is not None:
            rcd.stage = stage
            rcd.study_count = rcd.study_count + 1

        rcd.save()

        # 更新 session 的 completed_words
        if rcd.session:
            session = rcd.session
            completed = session.records.filter(study_count__gte=1).count()
            session.completed_words = completed
            session.check_completion()  # 检查是否需要结束会话

        return Response({"detail": "更新背诵记录成功。"})

class ReviewWordsView(APIView):
    """
    GET: 返回需要复习的单词列表( next_review_date <= today )
    """
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        user = request.user
        today = timezone.now().date()
        records_to_review = ReciteRecord.objects.filter(
            user=user,
            next_review_date__lte=today
        ).order_by('next_review_date')

        serializer = ReciteRecordSerializer(records_to_review, many=True)
        return Response(serializer.data)


class AllReviewWordsView(APIView):
    """
    GET: 返回所有已背过一次的单词列表 (study_count >=1 )
    """
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        user = request.user
        records_to_review = ReciteRecord.objects.filter(
            user=user,
            study_count__gte=1
        ).order_by('last_study_time')

        serializer = ReciteRecordSerializer(records_to_review, many=True)
        return Response(serializer.data)


# views.py

class CancelReciteView(APIView):
    """
    POST: 取消背诵或复习，设置会话的 end_time，并根据会话类型删除相关记录。
    Body:
    {
        "session_id": 999
    }
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user
        session_id = request.data.get("session_id", None)

        if session_id:
            try:
                session_obj = ReciteSession.objects.get(id=session_id, user=user)
            except ReciteSession.DoesNotExist:
                return Response({"detail": "Session 不存在或不属于您"}, status=status.HTTP_404_NOT_FOUND)

            # 设置 end_time 以结束会话
            session_obj.end_time = timezone.now()
            session_obj.save()

            # 根据会话类型决定是否删除 ReciteRecord
            if session_obj.session_type in [
                ReciteSession.SessionType.RECITATION,

            ]:
                # 删除关联的 ReciteRecord
                ReciteRecord.objects.filter(session=session_obj).delete()

            return Response({
                "detail": f"Session({session_id}) 已成功取消。"
            }, status=status.HTTP_200_OK)

        else:
            return Response({
                "detail": "请在请求体中提供 session_id。"
            }, status=status.HTTP_400_BAD_REQUEST)


class EndSessionView(APIView):
    """
    POST: 结束一个 ReciteSession，设置 end_time
    Body:
    {
        "session_id": 999
    }
    """
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        user = request.user
        session_id = request.data.get("session_id", None)

        if not session_id:
            return Response({"detail": "session_id 必填"}, status=status.HTTP_400_BAD_REQUEST)

        try:
            session = ReciteSession.objects.get(id=session_id, user=user)
        except ReciteSession.DoesNotExist:
            return Response({"detail": "Session 不存在或不属于您"}, status=status.HTTP_404_NOT_FOUND)

        # 结束会话
        session.end_time = timezone.now()
        session.save()

        return Response({
            "detail": f"Session({session_id}) 已成功结束。"
        }, status=status.HTTP_200_OK)

class OngoingSessionsView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        user = request.user

        # 获取所有未设置 end_time 的 ReciteSession
        ongoing_sessions = ReciteSession.objects.filter(user=user, end_time__isnull=True)

        sessions_data = []
        for session in ongoing_sessions:
            session_data = ReciteSessionSerializer(session).data
            records = ReciteRecord.objects.filter(session=session)

            records_data = []
            for rcd in records:
                rcd_ser = ReciteRecordSerializer(rcd).data
                # 额外拼接 word 详细信息
                word_details = get_word_details(rcd.word_type, rcd.word_id)
                # 将单词详情合并到 rcd_ser
                rcd_ser.update(word_details)
                records_data.append(rcd_ser)

            session_data['records'] = records_data
            sessions_data.append(session_data)

        return Response({
            "ongoing_sessions": sessions_data
        }, status=status.HTTP_200_OK)